/**
 * 数据库管理页面路由
 */

var router = require('express').Router();
var dbentityTool = require('../bin/dbentity');
var ObjectID = require('mongodb').ObjectID;
var redisentityTool = require('../bin/redisentity');
var userTool = require('../bin/user');
var articleTool = require('../bin/article');
var fondTool = require('../bin/fond');
var commentTool = require('../bin/comment');
var assertAlljs = require('../bin/util/assert-alljs');
var datetimeTool = require('../bin/util/datetime');

router.get('/manageEverything(.*)?', async function(req, res) {
    let user = req.session.user;
    let assert = assertAlljs(req, res);
    let checkMessage = userTool.check(user, {role: 'admin'});
    if (await assert(checkMessage))
        return;

    if (await assert(req.query.col == null || req.query.col === ''))
        return;
    let col = req.query.col;

    let filter = null;
    if (req.query.filter != null && req.query.filter !== ''){
        try{
            filter = JSON.parse(req.query.filter);
            if (filter != null && '_id' in filter){
                filter['_id'] = ObjectID(filter['_id']);
            }
        }catch(e){
            if (await assert(e))
                return;
        }
    }

    let sort = null;
    if (req.query.sort != null && req.query.sort !== ''){
        try{
            sort = JSON.parse(req.query.sort);
        }catch(e){
            sort = null;
        }
    }

    let page = parseInt(req.query.page);
    if (isNaN(page) || page < 1)
        page = 1;

    let option = { skip : (page-1)*100, limit : 100 };
    if (sort != null)
        option.sort = sort;
    let docs = await dbentityTool.find(col, filter, option);
    if (await assert(docs instanceof Error))
        return;

    docs.forEach(function(doc){
        doc.infoUrl = '';
        if (col === 'user') {
            doc.infoUrl = './user?id=' + doc._id;
            delete doc['password_n'];
            delete doc['password_e'];
            delete doc['password_p'];
            if (typeof(doc.signupdate) === 'number')
                doc.signupdate = datetimeTool.to_yMdHms(doc.signupdate, '', '-', '', '-');
        }else if (col === 'article') {
            doc.infoUrl = './article?id=' + doc._id;
            if (typeof(doc.produceTime) === 'number')
                doc.produceTime = datetimeTool.to_yMdHms(doc.produceTime, '', '-', '', '-');
        }else if (col === 'comment' || col === 'fond' ) {
            doc.infoUrl = './article?id=' + doc.article_id + '&&path=' + doc.path;
            if (typeof(doc.produceTime) === 'number')
                doc.produceTime = datetimeTool.to_yMdHms(doc.produceTime, '', '-', '', '-');
        }else if (col === 'feedback') {
            doc.infoUrl = doc.url;
            if (typeof(doc.produceTime) === 'number')
                doc.produceTime = datetimeTool.to_yMdHms(doc.produceTime, '', '-', '', '-');
        }else if (col === 'behavior' ) {
            if (typeof(doc.t) === 'number')
                doc.t = datetimeTool.to_yMdHms(doc.t, '', '-', '', '-');
        }
    });

    let local = {col:req.query.col, filter:req.query.filter, items:docs, fields:[], sort:req.query.sort, page:{ pageno:page, from:(page-1)*100 + 1, to:page*100 }};
    for (let ikey in local.items){
        let item = local.items[ikey];
        for (let key in item){
            if (typeof(item[key]) === 'function'){
                delete item[key];
                continue;
            }

            if (local.fields.indexOf(key) < 0 && key !== 'infoUrl')
                local.fields.push(key);

            try{
                item[key] = JSON.stringify(item[key]).replace(/(^"|"$)/g, '');
            }catch(e){
                item[key] = '[JSON.stringify error]'
            }
        }

    }
    res.render('dyn.manageEverything.html', local);
});

router.post('/deleteSomething', async function(req, res) {
    let user = req.session.user;
    let assert = assertAlljs(req, res);

    if (await assert(req.body.col == null || req.body.col === ''))
        return;
    let col = req.body.col;

    let type = req.body.type;

    let filter = {};
    if (req.body.filter != null && req.body.filter !== ''){
        try{
            filter = JSON.parse(req.body.filter);
            if (filter != null && '_id' in filter){
                filter['_id'] = ObjectID(filter['_id']);
            }
        }catch(e){
            if (await assert(e))
                return;
        }
    }

    req.behavior.set(JSON.stringify({col, type, filter}));
    if (type === 'forbid'){
        if (await assert(!(col === 'user' || col === 'article'), 'FORBID/PERMIT only support user & article entity'))
            return;

        let checkMessage = userTool.check(user, {role: col==='user'?'admin':['admin', 'admin:'+res.locals.blockRoot]});
        if (await assert(checkMessage))
            return;

        let docs = await dbentityTool.find(col, filter);
        if (await assert(docs instanceof Error))
            return;

        let doPermit = docs.every((doc) => doc.status === 1);
        let status = doPermit ? 0 : 1;

        let result = await dbentityTool.updateMany(col, filter, {$set:{status}});
        if (await assert(result instanceof Error))
            return;

        // 如果禁用的是user，则还要删除session
        if (col === 'user' && !doPermit){
            let sesids = await redisentityTool.findIds('ses');
            if (sesids instanceof Array){
                let user_ids = docs.map((doc) => doc._id);
                let forbidSelf = false;
                for (let sesid of sesids){
                    let ses = await redisentityTool.get('ses', sesid);
                    if (!(ses instanceof Error) && ('user' in ses) && (user_ids.indexOf(ses.user._id)>-1) ){
                        if (ses.user._id === req.session.user._id){
                            forbidSelf = true;
                            req.session.signout();
                        } else {
                            await redisentityTool.set('sso', ses.user._id + '_web', null);
                            delete ses.user;
                            ses.signouttime = new Date().getTime();
                            await redisentityTool.set('ses', sesid, ses);
                        }
                    }
                }
                if (forbidSelf){
                    await  req.session.pushMessage((doPermit ? 'PERMIT ' : 'FORBID ') + result.modifiedCount + ' records');
                    res.redirect('./');
                    return;
                }
            }
        }

        await assert(true, (doPermit ? 'PERMIT ' : 'FORBID ') + result.modifiedCount + ' records');
        return;
    }

    let checkMessage = userTool.check(user, {role: 'admin'});
    if (await assert(checkMessage))
        return;

    if (col === 'fond'){
        let result = await dbentityTool.find('fond', filter);
        if (await assert(result instanceof Error))
            return;
        let deletedCount = 0;
        for (let fond of result){
            let result2 = await fondTool.deleteFond(fond._id);
            if (!(result2 instanceof Error))
                deletedCount++;
        }
        await assert(true, 'deleted ' + deletedCount + ' records');

    } else if (col === 'comment'){
        let result = await dbentityTool.find('comment', filter);
        if (await assert(result instanceof Error))
            return;
        let deletedCount = 0;
        for (let comment of result){
            let result2 = await commentTool.deleteComment(comment._id);
            if (!(result2 instanceof Error))
                deletedCount++;
        }
        await assert(true, 'deleted ' + deletedCount + ' records');

    } else if (col === 'article'){
        if (await assert(filter == null || !('_id' in filter), 'article should be deleted ONE BY ONE'))
            return;
        let result = await articleTool.deleteArticle(filter._id);
        if (await assert(result instanceof Error))
            return;
        await assert(true, 'deleted ' + result.deletedCount + ' records');

    } else if (col === 'user'){
        if (await assert(filter == null || !('_id' in filter), 'user should be deleted ONE BY ONE'))
            return;
        let result = await userTool.deleteUser(filter._id);
        if (await assert(result instanceof Error))
            return;
        await assert(true, 'deleted ' + result.deletedCount + ' records');

    } else {
        let result = await dbentityTool.deleteMany(col, filter);
        if (await assert(result instanceof Error))
            return;
        await assert(true, 'deleted ' + result.deletedCount + ' records');
    }
});

module.exports = router;